extends CharacterBody2D
class_name BaseEnemy

# 基础属性
@export var max_health: int = 50
@export var speed: float = 50.0
@export var damage: int = 10
@export var detection_range: float = 80.0
@export var attack_range: float = 20.0
@export var attack_cooldown: float = 1.0

# 内部变量
var current_health: int
var player: CharacterBody2D
var is_attacking: bool = false
var attack_timer: float = 0.0
var is_dead: bool = false

# 状态枚举
enum State {
	IDLE,
	PATROL,
	CHASE,
	ATTACK,
	HURT,
	DEAD
}

var current_state: State = State.IDLE
var state_timer: float = 0.0

# 节点引用
@onready var sprite: Sprite2D = $Sprite2D
@onready var animation_player: AnimationPlayer = $AnimationPlayer
@onready var detection_area: Area2D = $DetectionArea
@onready var detection_collision: CollisionShape2D = $DetectionArea/DetectionCollision
@onready var health_bar: EnemyHealthBar = $HealthBar
@onready var damage_label: Label = $DamageLabel

# 信号
signal died(enemy: BaseEnemy)
signal player_detected(player: CharacterBody2D)
signal health_changed(current: int, maximum: int)

# 添加边界检测变量
var game_bounds: Rect2
var half_sprite_size: Vector2
var tilemap: TileMap  # TileMap引用

func _ready():
	setup_enemy()
	setup_detection()
	setup_ui()
	setup_screen_bounds()

func setup_enemy():
	current_health = max_health
	collision_layer = 4  # 敌人层
	collision_mask = 3   # 与玩家(1)和墙壁(2)碰撞 (1+2=3)
	
	print("🎯 敌人 ", name, " 碰撞设置: layer=", collision_layer, " mask=", collision_mask)
	
	# 设置检测区域
	if detection_collision:
		var circle_shape = CircleShape2D.new()
		circle_shape.radius = detection_range
		detection_collision.shape = circle_shape

func setup_detection():
	if detection_area:
		detection_area.body_entered.connect(_on_detection_area_entered)
		detection_area.body_exited.connect(_on_detection_area_exited)

func setup_ui():
	# 设置血条
	if health_bar:
		health_bar.set_health(current_health, max_health)
		health_bar.visible = false
	
	# 设置伤害标签
	if damage_label:
		damage_label.visible = false

func setup_screen_bounds():
	# 获取TileMap引用
	if not tilemap:
		var game_node = get_tree().get_first_node_in_group("game")
		if game_node:
			tilemap = game_node.get_node_or_null("TileMap")
	
	# 基于TileMap尺寸设置游戏边界
	if tilemap:
		# 获取TileMap的使用区域
		var used_rect = tilemap.get_used_rect()
		var tile_size = tilemap.tile_set.tile_size if tilemap.tile_set else Vector2i(16, 16)
		
		# 计算实际的世界坐标边界
		var world_start = tilemap.map_to_local(used_rect.position)
		var world_end = tilemap.map_to_local(used_rect.position + used_rect.size)
		
		game_bounds = Rect2(world_start, world_end - world_start)
		# print("🗺️ 敌人 ", name, " 边界设置为TileMap范围: ", game_bounds)
	else:
		# 回退到viewport尺寸
		var viewport_size = get_viewport().get_visible_rect().size
		game_bounds = Rect2(Vector2.ZERO, viewport_size)
		# print("⚠️ 敌人 ", name, " 未找到TileMap，使用viewport边界: ", game_bounds)
	
	# 计算精灵的一半大小作为边界偏移
	if sprite and sprite.texture:
		half_sprite_size = sprite.texture.get_size() / 2
	else:
		half_sprite_size = Vector2(8, 8)  # 默认值

func _physics_process(delta):
	if is_dead:
		return
	
	update_timers(delta)
	update_state_machine(delta)
	move_and_slide()
	clamp_to_screen_bounds()  # 添加边界检测
	update_sprite_direction()

func update_timers(delta):
	if attack_timer > 0:
		attack_timer -= delta
	state_timer += delta

func update_state_machine(delta):
	match current_state:
		State.IDLE:
			handle_idle_state(delta)
		State.PATROL:
			handle_patrol_state(delta)
		State.CHASE:
			handle_chase_state(delta)
		State.ATTACK:
			handle_attack_state(delta)
		State.HURT:
			handle_hurt_state(delta)

# 虚函数 - 子类重写
func handle_idle_state(delta):
	velocity = Vector2.ZERO

func handle_patrol_state(delta):
	# 基础巡逻逻辑 - 子类可重写
	pass

func handle_chase_state(delta):
	if player:
		var distance_to_player = global_position.distance_to(player.global_position)
		
		# 如果距离太近，停止移动避免黏着
		if distance_to_player <= attack_range:
			velocity = Vector2.ZERO
			if attack_timer <= 0:
				change_state(State.ATTACK)
		else:
			# 保持合适距离的追击
			var direction = (player.global_position - global_position).normalized()
			velocity = direction * speed

func handle_attack_state(delta):
	velocity = Vector2.ZERO
	if not is_attacking and attack_timer <= 0:
		perform_attack()

func handle_hurt_state(delta):
	# 受伤时逐渐减速（击退效果）
	velocity = velocity.move_toward(Vector2.ZERO, 200.0 * delta)
	
	if state_timer >= 0.5:  # 受伤状态持续0.5秒
		if player and global_position.distance_to(player.global_position) <= detection_range:
			change_state(State.CHASE)
		else:
			change_state(State.IDLE)

func change_state(new_state: State):
	current_state = new_state
	state_timer = 0.0

func perform_attack():
	is_attacking = true
	attack_timer = attack_cooldown
	
	# 播放攻击动画
	if animation_player:
		animation_player.play("attack")
	
	# 检测玩家是否在攻击范围内
	if player and global_position.distance_to(player.global_position) <= attack_range:
		# 对玩家造成伤害
		if player.has_method("take_damage"):
			player.take_damage(damage)
	
	# 等待攻击动画结束
	await get_tree().create_timer(0.5).timeout
	is_attacking = false
	
	# 攻击后短暂后退避免黏着
	if player:
		var retreat_direction = (global_position - player.global_position).normalized()
		velocity = retreat_direction * speed * 0.5
		await get_tree().create_timer(0.3).timeout
	
	change_state(State.CHASE)

func take_damage(amount: int):
	# print("💔 ", name, " 受到伤害: ", amount, " HP: ", current_health, "->", max(0, current_health - amount))
	
	if is_dead:
		# print("💀 敌人已死亡，忽略伤害")
		return
	
	current_health = max(0, current_health - amount)
	health_changed.emit(current_health, max_health)
	
	# 添加击退效果
	apply_knockback()
	
	# print("🩸 显示UI效果...")
	
	# 显示血条
	# print("📊 显示血条...")
	show_health_bar()
	
	# 显示伤害数字
	# print("💥 显示伤害数字...")
	show_damage_number(amount)
	
	# 受伤效果
	# print("🔴 显示受伤效果...")
	show_hurt_effect()
	
	# 血条动画效果
	if health_bar:
		health_bar.animate_damage()
	
	if current_health <= 0:
		# print("💀 敌人死亡: ", name)
		die()
	else:
		change_state(State.HURT)

func show_health_bar():
	if health_bar and not is_dead:
		health_bar.set_health(current_health, max_health)
		health_bar.show_health_bar()
		
		# 敌人血条2秒后隐藏（比玩家更快）
		health_bar.hide_health_bar(2.0)

func show_damage_number(amount: int):
	if damage_label and not is_dead:
		damage_label.text = str(amount)
		damage_label.visible = true
		damage_label.modulate = Color.YELLOW  # 使用黄色更醒目
		damage_label.scale = Vector2(1.5, 1.5)  # 初始放大
		
		var tween = create_tween()
		if tween and damage_label:
			var start_pos = damage_label.position.y
			# 更醒目的伤害数字动画
			tween.parallel().tween_property(damage_label, "position:y", start_pos - 30, 0.8)
			tween.parallel().tween_property(damage_label, "scale", Vector2(1.0, 1.0), 0.2)
			tween.parallel().tween_property(damage_label, "modulate:a", 0.0, 0.6)
			tween.tween_callback(func(): if damage_label and is_instance_valid(damage_label): 
				damage_label.visible = false
				damage_label.scale = Vector2(1.0, 1.0)  # 重置缩放
			)

func apply_knockback():
	# 计算击退方向（远离玩家）
	if player and not is_dead:
		var knockback_direction = (global_position - player.global_position).normalized()
		var knockback_force = 100.0
		
		# 应用击退速度
		velocity = knockback_direction * knockback_force

func show_hurt_effect():
	if sprite and not is_dead:
		var tween = create_tween()
		if tween and sprite:
			# 增强受击效果：更长时间的闪红，并加入放大效果
			tween.parallel().tween_property(sprite, "modulate", Color.RED, 0.1)
			tween.parallel().tween_property(sprite, "scale", Vector2(1.1, 1.1), 0.1)
			tween.parallel().tween_property(sprite, "modulate", Color.WHITE, 0.3)
			tween.parallel().tween_property(sprite, "scale", Vector2(1.0, 1.0), 0.3)

func die():
	if is_dead:  # 防止重复调用
		return
		
	is_dead = true
	current_state = State.DEAD
	
	# print("💀 敌人开始死亡流程: ", name)
	
	# 播放死亡动画
	if animation_player and animation_player.has_animation("death"):
		animation_player.play("death")
	
	# 禁用碰撞
	collision_layer = 0
	collision_mask = 0
	
	# 隐藏UI元素
	if health_bar:
		health_bar.visible = false
	if damage_label:
		damage_label.visible = false
	
	# 发出死亡信号
	died.emit(self)
	
	# 死亡特效
	create_death_effect()
	
	# 延迟销毁
	await get_tree().create_timer(1.0).timeout
	if is_instance_valid(self):
		queue_free()

func create_death_effect():
	# 创建死亡爆炸特效
	if get_parent():
		var explosion = Sprite2D.new()
		get_parent().add_child(explosion)
		explosion.global_position = global_position
		explosion.texture = load("res://Art/v1.1 dungeon crawler 16X16 pixel pack/effects (new)/enemy_afterdead_explosion_anim_spritesheet.png")
		explosion.hframes = 4
		explosion.name = "EnemyDeathExplosion_" + str(get_instance_id())  # 使用唯一名称
		
		var tween = create_tween()
		var explosion_name = explosion.name
		if tween:
			tween.tween_method(
				func(frame): 
					var parent = get_parent()
					if parent:
						var effect = parent.get_node_or_null(NodePath(explosion_name))
						if effect:
							effect.frame = frame, 
				0, 3, 0.4
			)
			tween.tween_callback(
				func(): 
					var parent = get_parent()
					if parent:
						var effect = parent.get_node_or_null(NodePath(explosion_name))
						if effect:
							effect.queue_free()
			)

func update_sprite_direction():
	if velocity.x < 0:
		sprite.flip_h = true
	elif velocity.x > 0:
		sprite.flip_h = false

func _on_detection_area_entered(body):
	if body.name == "Player":
		player = body
		player_detected.emit(body)
		if current_state == State.IDLE or current_state == State.PATROL:
			change_state(State.CHASE)

func _on_detection_area_exited(body):
	if body == player:
		player = null
		if current_state == State.CHASE:
			change_state(State.IDLE)

func safe_play_animation(anim_name: String):
	if animation_player and animation_player.has_animation(anim_name):
		if animation_player.current_animation != anim_name:
			animation_player.play(anim_name)

func get_or_create_animation_library() -> AnimationLibrary:
	var library = animation_player.get_animation_library("")
	if library == null:
		library = AnimationLibrary.new()
		animation_player.add_animation_library("", library)
	return library

# 添加边界检测函数（现在主要作为物理碰撞的补充）
func clamp_to_screen_bounds():
	# 如果游戏边界还没有正确设置，尝试重新设置
	if game_bounds.size.x <= 0 or game_bounds.size.y <= 0:
		setup_screen_bounds()
		return
	
	# 由于现在有了物理碰撞，边界检测主要用于防止敌人离开地图边缘
	var margin = 8.0  # 边界余量
	var clamped_x = clamp(global_position.x, game_bounds.position.x + margin, 
						 game_bounds.position.x + game_bounds.size.x - margin)
	var clamped_y = clamp(global_position.y, game_bounds.position.y + margin, 
						 game_bounds.position.y + game_bounds.size.y - margin)
	
	# 只有当敌人确实超出边界时才进行调整
	if global_position.x != clamped_x or global_position.y != clamped_y:
		global_position = Vector2(clamped_x, clamped_y)
		# print("🚧 敌人 ", name, " 位置被边界限制: ", global_position)

# 重置敌人状态（用于重新开始游戏）
func reset_enemy():
	print("🔄 重置敌人: ", name)
	
	# 重置生命值和状态
	current_health = max_health
	is_dead = false
	is_attacking = false
	attack_timer = 0.0
	state_timer = 0.0
	player = null
	
	# 重置碰撞层
	collision_layer = 4  # 敌人层
	collision_mask = 3   # 与玩家(1)和墙壁(2)碰撞 (1+2=3)
	
	# 重置外观
	if sprite:
		sprite.modulate = Color.WHITE
		sprite.scale = Vector2(1, 1)
		sprite.rotation = 0
	
	# 重置状态
	change_state(State.IDLE)
	
	# 隐藏UI元素
	if health_bar:
		health_bar.visible = false
		health_bar.set_health(current_health, max_health)
	
	if damage_label:
		damage_label.visible = false
	
	# 重置速度
	velocity = Vector2.ZERO
	
	# 重新启用处理
	set_physics_process(true)
	set_process(true)
	
	print("✅ 敌人重置完成: ", name)
